
#ifndef _M_HELPER_S
#define _M_HELPER_S
#include <iostream>
#include<fstream>
#include<sqlite3.h>
#include<string>
#include<vector>
#include"mq_logger.hpp"
#include<random>
#include<sstream>
#include<iomanip>
#include<atomic>
#include<sys/stat.h>
#include<cstring>
#include<cerrno>
namespace ljhmq
{
class SqliteHelper
{
public:
typedef int (*SqliteCallback)(void*,int,char**,char**);
SqliteHelper(const std::string& dbfile):_dbfile(dbfile){}

//打开
//int sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs );
bool open(int safe_leve=SQLITE_OPEN_FULLMUTEX)
{
  DLOG("_dbfile:%s", _dbfile.c_str());
  int ret = sqlite3_open_v2(_dbfile.c_str(), &_handler, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | safe_leve, nullptr);
  if (ret != SQLITE_OK)
  {
    // std::cout<<"创建/打开数据库失败：";
    // std::cout<<sqlite3_errmsg(_handler)<<std::endl;
    ELOG("创建/打开数据库失败：%s", sqlite3_errmsg(_handler));
    return false;
}
ELOG("创建/打开数据库成功！！！");
return true;
}
//执行sql语句
//int sqlite3_exec(sqlite3*, char *sql, int (*callback)(void*,int,char**,char**), void* arg, char **err)
bool exec(const std::string& sql,SqliteCallback cb,void *arg)
{
 int ret=sqlite3_exec(_handler,sql.c_str(),cb,arg,nullptr);
    if(ret!=SQLITE_OK)
    {
      //  std::cout<<sql;
       // std::cout<<"执行语句失败：";
       // std::cout<<sqlite3_errmsg(_handler)<<std::endl;
       ELOG(" %s 执行语句失败：%s",sql.c_str(),sqlite3_errmsg(_handler));
        return false;
    }
return true;
}
//关闭
void close(){
//int sqlite3_close_v2(sqlite3*);
if(_handler) sqlite3_close_v2(_handler);
}
private:
std::string _dbfile;
sqlite3* _handler;
};

class StrHelper
{
public:
static int split(const std::string& str,const std::string &sep,std::vector<std::string>& result)
{
   size_t pos,idx=0;
   while(idx<str.size())
   {
     pos=str.find(sep,idx);
     if(pos==std::string::npos)
     {
        return result.size();
     }

      if(pos==idx)
      {
        idx=pos+sep.size();
        continue;
      }
     result.push_back(str.substr(idx,pos-idx));
     idx=pos+sep.size();

   } 
 return result.size();
   }
};



class UUIDHelper
{
public:
static  std::string uuid()
{
std::random_device rd;

std::mt19937_64 gernator(rd());

std::uniform_int_distribution<int> distribution(0,255);
std::cout<<distribution(gernator)<<std::endl;

std::stringstream ss;
for(int i=0;i<8;i++)
{
    ss<<std::setw(2)<<std::setfill('0')<<std::hex<<distribution(gernator);
     if(i==3||i==5||i==7)
     ss<<"-";
}

static std::atomic<size_t>seq(1);
size_t num=seq.fetch_add(1);
for(int i=7;i>=0;i--)
{
    ss<<std::setw(2)<<std::setfill('0')<<std::hex<<((num>>(i*8))&0xff);
    if(i==6)
    ss<<"-";
}
 return ss.str();
}

};

class FileHelper
{
public:
FileHelper(const std::string& filename):_filename(filename){}
 bool exists()
{
  struct stat st;
  return (stat(_filename.c_str(),&st)==0);
}
size_t size()
{
  struct stat st;
  int ret=stat(_filename.c_str(),&st);
  if(ret<0)
  return 0;

  return st.st_size;
}

bool read(char* body,size_t offset,size_t len)
{
  //1.打开文件
  std::ifstream ifs(_filename.c_str(), std::ios::binary|std::ios::in);
  if(ifs.is_open()==false)
  {
    ELOG("%s 文件打开失败:%s", _filename.c_str(),strerror(errno));
    return false;
  }
   //2.跳转文件读写的位置
   ifs.seekg(offset,std::ios::beg);
   //3.读取文件
   ifs.read(body,len);
   if(ifs.good()==false)
   {
    ELOG("%s 文件读取数据失败！！",_filename.c_str())
    ifs.close();
    return false;
   }
   //关闭文件
   ifs.close();
   return true;

}
bool read(std::string& body)
{
  size_t fsize=this->size();
  //std::cout << "size:" << fsize;
  body.resize(fsize);
  return read(&body[0], 0, fsize);
}

bool write(const std::string&body ,size_t offset,size_t len)
{//1.打开文件
  std::fstream ifs(_filename.c_str(),std::ios::binary|std::ios::out| std::ios::in);
      if(ifs.is_open()==false)
      {
        ELOG("%s 文件打开失败",_filename.c_str());
        return false;
      }
   //2.跳转文件读写的位置
   ifs.seekg(offset,std::ios::beg);
   //3.读取文件
   ifs.write(body.c_str(),len);
   if(ifs.good()==false)
   {
    ELOG("%s 文件写入数据失败！！",_filename.c_str())
    ifs.close();
    return false;
   }
   //关闭文件
   ifs.close();
   return true;

}
bool write(const std::string& body)
{
  return write(body.c_str(),0,body.size());
}
bool rename(const std::string& nname)
{
  //DLOG("临时文件%s和源文件%s", _filename.c_str(), nname.c_str());
  // return ::rename(_filename.c_str(), nname.c_str());
  return (::rename(_filename.c_str(), nname.c_str()) == 0);//在系统调用中，成功一般返回是0，但是0是在bool中表示false
}
static bool createFile(const std::string& _filename)
{
  //1.打开文件
  std::fstream ofs(_filename,std::ios::binary| std::ios::out);
      if(ofs.is_open()==false)
      {
        ELOG("%s 文件打开失败!",_filename.c_str());
        return false;
      }
      ofs.close();
      return true;
      
}
static bool removeFile(const std::string& _filename)
{
  return (::remove(_filename.c_str())==0);
}
static bool createDirectory(const std::string &path)
{
  //多级路径创建中，需要从第一个父级目录开始创建
  size_t pos,idx=0;
  while(idx<path.size())
  {
    pos=path.find("/",idx);
    if(pos==std::string::npos)
    {
      std::string subpath=path.substr(idx);
      return (mkdir(path.c_str(),0775)==0);
    }

    std::string subpath=path.substr(0,pos);
    int ret=mkdir(subpath.c_str(),0775);
    if(ret!=0&&errno!=EEXIST)
    {
      ELOG("创建目录: %s失败:%s",subpath.c_str(),strerror(errno));
      return false;
    }

      idx=pos+1;
  }
 
 return true;

}
static bool removeDirectory(const std::string& path)
{
  std::string cmd="rm -rf "+path;
  return (system(cmd.c_str())!=-1);
}
static std::string parentDirectory(const std::string& filename)
{
  size_t pos=filename.find_last_of("/");
  if(pos==std::string::npos)
  {
    return "./";
  }
  std::string path=filename.substr(0,pos);
  return path;
}
private:
 std::string _filename;

};


}
#endif